<template>
	<view class="tui-datetime-picker">
		<view class="tui-mask" :class="{ 'tui-mask-show': isShow }" @touchmove.stop.prevent="stop" catchtouchmove="stop" @tap="maskClick"></view>
		<view class="tui-header" :class="{ 'tui-show': isShow }">
			<view
				class="tui-picker-header"
				:class="{ 'tui-date-radius': radius }"
				:style="{ backgroundColor: headerBackground }"
				@touchmove.stop.prevent="stop"
				catchtouchmove="stop"
			>
				<view class="tui-btn-picker" :style="{ color: cancelColor }" hover-class="tui-opacity" :hover-stay-time="150" @tap="hide">取消</view>
				<view class="tui-btn-picker" :style="{ color: color }" hover-class="tui-opacity" :hover-stay-time="150" @tap="btnFix">确定</view>
			</view>
			<view class="tui-date-header" :style="{ backgroundColor: unitBackground }" v-if="unitTop">
				<view class="tui-date-unit" v-if="type < 4 || type == 7 || type == 8">年</view>
				<view class="tui-date-unit" v-if="type < 4 || type == 7 || type == 8">月</view>
				<view class="tui-date-unit" v-if="type == 1 || type == 2 || type == 7 || type == 8">日</view>
				<view class="tui-date-unit" v-if="type == 1 || type == 4 || type == 5 || type == 7 || type == 8">时</view>
				<view class="tui-date-unit" v-if="(type == 1 || type > 3) && type != 8">分</view>
				<view class="tui-date-unit" v-if="type > 4 && type != 8">秒</view>
			</view>
			<view class="tui-date__picker-body" :style="{ backgroundColor: bodyBackground, height: height + 'rpx' }">
				<picker-view :value="value" @change="change" class="tui-picker-view">
					<picker-view-column v-if="!reset && (type < 4 || type == 7 || type == 8)">
						<view class="tui-date__column-item" :class="{ 'tui-font-size_32': !unitTop && type == 7 }" v-for="(item, index) in years" :key="index">
							{{ item }}
							<text class="tui-date__unit-text" v-if="!unitTop">年</text>
						</view>
					</picker-view-column>
					<picker-view-column v-if="!reset && (type < 4 || type == 7 || type == 8)">
						<view class="tui-date__column-item" :class="{ 'tui-font-size_32': !unitTop && type == 7 }" v-for="(item, index) in months" :key="index">
							{{ formatNum(item) }}
							<text class="tui-date__unit-text" v-if="!unitTop">月</text>
						</view>
					</picker-view-column>
					<picker-view-column v-if="!reset && (type == 1 || type == 2 || type == 7 || type == 8)">
						<view class="tui-date__column-item" :class="{ 'tui-font-size_32': !unitTop && type == 7 }" v-for="(item, index) in days" :key="index">
							{{ formatNum(item) }}
							<text class="tui-date__unit-text" v-if="!unitTop">日</text>
						</view>
					</picker-view-column>
					<picker-view-column v-if="!reset && (type == 1 || type == 4 || type == 5 || type == 7 || type == 8)">
						<view class="tui-date__column-item" :class="{ 'tui-font-size_32': !unitTop && type == 7 }" v-for="(item, index) in hours" :key="index">
							{{ formatNum(item) }}
							<text class="tui-date__unit-text" v-if="!unitTop">时</text>
						</view>
					</picker-view-column>
					<picker-view-column v-if="!reset && (type == 1 || type > 3) && type != 8">
						<view class="tui-date__column-item" :class="{ 'tui-font-size_32': !unitTop && type == 7 }" v-for="(item, index) in minutes" :key="index">
							{{ formatNum(item) }}
							<text class="tui-date__unit-text" v-if="!unitTop">分</text>
						</view>
					</picker-view-column>
					<picker-view-column v-if="!reset && type > 4 && type != 8">
						<view class="tui-date__column-item" :class="{ 'tui-font-size_32': !unitTop && type == 7 }" v-for="(item, index) in seconds" :key="index">
							{{ formatNum(item) }}
							<text class="tui-date__unit-text" v-if="!unitTop">秒</text>
						</view>
					</picker-view-column>
				</picker-view>
			</view>
		</view>
	</view>
</template>

<script setup>
import { ref, reactive, toRefs, computed, watch, onBeforeMount, onMounted } from 'vue'

const emit = defineEmits(['cancel', 'confirm'])

const props = defineProps({
	//1-日期+时间（年月日+时分） 2-日期(年月日) 3-日期(年月) 4-时间（时分） 5-时分秒
	//6-分秒 7-年月日 时分秒 8-年月日+小时
	type: {
		type: Number,
		default: 1
	},
	//"取消"字体颜色
	cancelColor: {
		type: String,
		default: '#888'
	},
	//"确定"字体颜色
	color: {
		type: String,
		default: '#5677fc'
	},
	//设置默认显示日期 2019-08-01 || 2019-08-01 17:01 || 2019/08/01
	setDateTime: {
		type: String,
		default: ''
	},
	//单位置顶
	unitTop: {
		type: Boolean,
		default: false
	},
	//圆角设置
	radius: {
		type: Boolean,
		default: false
	},
	//头部背景色
	headerBackground: {
		type: String,
		default: '#fff'
	},
	//根据实际调整，不建议使用深颜色
	bodyBackground: {
		type: String,
		default: '#fff'
	},
	//单位置顶时，单位条背景色
	unitBackground: {
		type: String,
		default: '#fff'
	},
	height: {
		type: [Number, String],
		default: 520
	},
	//点击遮罩 是否可关闭
	maskClosable: {
		type: Boolean,
		default: true
	}
})

const state = reactive({
	isShow: false,
	years: [],
	months: [],
	days: [],
	hours: [],
	minutes: [],
	seconds: [],
	year: 0,
	month: 0,
	day: 0,
	hour: 0,
	minute: 0,
	second: 0,
	startDate: '',
	endDate: '',
	value: [0, 0, 0, 0, 0, 0],
	reset: false
})

const yearOrMonth = computed(() => `${state.year}-${state.month}`)
const propsChange = computed(() => `${props.setDateTime}-${props.type}`)

watch(yearOrMonth, nVal => {
	setDays()
})

watch(propsChange, nVal => {
	state.reset = true
	setTimeout(() => {
		initData()
	}, 20)
})

onMounted(() => {
	setTimeout(() => {
		initData()
	}, 20)
})

const stop = () => {}

const formatNum = num => {
	return num < 10 ? '0' + num : num + ''
}

const generateArray = (start, end) => {
	return Array.from(new Array(end + 1).keys()).slice(start)
}

const getIndex = (arr, val) => {
	let index = arr.indexOf(val)
	return ~index ? index : 0
}

//日期时间处理
const initSelectValue = () => {
	let fdate = props.setDateTime.replace(/\-/g, '/')
	fdate = fdate && fdate.indexOf('/') == -1 ? `2020/01/01 ${fdate}` : fdate
	let time = null
	if (fdate) time = new Date(fdate)
	else time = new Date()
	state.year = time.getFullYear()
	state.month = time.getMonth() + 1
	state.day = time.getDate()
	state.hour = time.getHours()
	state.minute = time.getMinutes()
	state.second = time.getSeconds()
	console.log(time)
}

const initData = () => {
	initSelectValue()
	state.reset = false

	switch (props.type) {
		case 1:
			state.value = [0, 0, 0, 0, 0]
			setYears()
			setMonths()
			setDays()
			setHours()
			setMinutes()
			break
		case 2:
			state.value = [0, 0, 0]
			setYears()
			setMonths()
			setDays()
			break
		case 3:
			state.value = [0, 0]
			setYears()
			setMonths()
			break
		case 4:
			state.value = [0, 0]
			setHours()
			setMinutes()
			break
		case 5:
			state.value = [0, 0, 0]
			setHours()
			setMinutes()
			setSeconds()
			break
		case 6:
			state.value = [0, 0]
			setMinutes()
			setSeconds()
			break
		case 7:
			state.value = [0, 0, 0, 0, 0, 0]
			setYears()
			setMonths()
			setDays()
			setHours()
			setMinutes()
			setSeconds()
			break
		case 8:
			state.value = [0, 0, 0, 0]
			setYears()
			setMonths()
			setDays()
			setHours()
			break
		default:
			break
	}
}

const setYears = () => {
	const startYear = state.year - 3
	const endYear = state.year + 3
	state.years = generateArray(startYear, endYear)
	setTimeout(() => {
		state.value[0] = getIndex(state.years, state.year)
	}, 8)
}

const setMonths = () => {
	state.months = generateArray(1, 12)
	setTimeout(() => {
		state.value[1] = getIndex(state.months, state.month)
	}, 8)
}

const setDays = () => {
	if (props.type == 3 || props.type == 4) return
	const totalDays = new Date(state.year, state.month, 0).getDate()
	state.days = generateArray(1, totalDays)
	setTimeout(() => {
		state.value[2] = getIndex(state.days, state.day)
	}, 8)
}

const setHours = () => {
	state.hours = generateArray(0, 23)
	setTimeout(() => {
		let index = props.type == 5 || props.type == 7 ? state.value.length - 3 : props.type == 8 ? state.value.length - 1 : state.value.length - 2
		state.value[index] = getIndex(state.hours, state.hour)
	}, 8)
}

const setMinutes = () => {
	state.minutes = generateArray(0, 59)
	setTimeout(() => {
		let index = props.type > 4 ? state.value.length - 2 : state.value.length - 1
		state.value[index] = getIndex(state.minutes, state.minute)
	}, 8)
}

const setSeconds = () => {
	state.seconds = generateArray(0, 59)
	setTimeout(() => {
		state.value[state.value.length - 1] = getIndex(state.seconds, state.second)
	}, 8)
}

const show = () => {
	setTimeout(() => {
		state.isShow = true
	}, 50)
}

const hide = () => {
	state.isShow = false
	emit('cancel', {})
}

const maskClick = () => {
	if (!props.maskClosable) return
	hide()
}

const change = e => {
	state.value = e.detail.value

	switch (props.type) {
		case 1:
			state.year = state.years[state.value[0]]
			state.month = state.months[state.value[1]]
			state.day = state.days[state.value[2]]
			state.hour = state.hours[state.value[3]]
			state.minute = state.minutes[state.value[4]]
			break
		case 2:
			state.year = state.years[state.value[0]]
			state.month = state.months[state.value[1]]
			state.day = state.days[state.value[2]]
			break
		case 3:
			state.year = state.years[state.value[0]]
			state.month = state.months[state.value[1]]
			break
		case 4:
			state.hour = state.hours[state.value[0]]
			state.minute = state.minutes[state.value[1]]
			break
		case 5:
			state.hour = state.hours[state.value[0]]
			state.minute = state.minutes[state.value[1]]
			state.second = state.seconds[state.value[2]]
			break
		case 6:
			state.minute = state.minutes[state.value[0]]
			state.second = state.seconds[state.value[1]]
			break
		case 7:
			state.year = state.years[state.value[0]]
			state.month = state.months[state.value[1]]
			state.day = state.days[state.value[2]]
			state.hour = state.hours[state.value[3]]
			state.minute = state.minutes[state.value[4]]
			state.second = state.seconds[state.value[5]]
			break
		case 8:
			state.year = state.years[state.value[0]]
			state.month = state.months[state.value[1]]
			state.day = state.days[state.value[2]]
			state.hour = state.hours[state.value[3]]
			break
		default:
			break
	}
}

const btnFix = () => {
	setTimeout(() => {
		let result = {}
		let year = state.year
		let month = formatNum(state.month || 0)
		let day = formatNum(state.day || 0)
		let hour = formatNum(state.hour || 0)
		let minute = formatNum(state.minute || 0)
		let second = formatNum(state.second || 0)
		switch (props.type) {
			case 1:
				result = {
					year: year,
					month: month,
					day: day,
					hour: hour,
					minute: minute,
					result: `${year}-${month}-${day} ${hour}:${minute}`
				}
				break
			case 2:
				result = {
					year: year,
					month: month,
					day: day,
					result: `${year}-${month}-${day}`
				}
				break
			case 3:
				result = {
					year: year,
					month: month,
					result: `${year}-${month}`
				}
				break
			case 4:
				result = {
					hour: hour,
					minute: minute,
					result: `${hour}:${minute}`
				}
				break
			case 5:
				result = {
					hour: hour,
					minute: minute,
					second: second,
					result: `${hour}:${minute}:${second}`
				}
				break
			case 6:
				result = {
					minute: minute,
					second: second,
					result: `${minute}:${second}`
				}
				break
			case 7:
				result = {
					year: year,
					month: month,
					day: day,
					hour: hour,
					minute: minute,
					second: second,
					result: `${year}-${month}-${day} ${hour}:${minute}:${second}`
				}
				break
			case 8:
				result = {
					year: year,
					month: month,
					day: day,
					hour: hour,
					result: `${year}-${month}-${day} ${hour}:00`
				}
				break
			default:
				break
		}

		emit('confirm', result)
		hide()
	}, 80)
}

const { isShow, years, months, days, hours, minutes, seconds, year, month, day, hour, minute, second, startDate, endDate, value, reset } = toRefs(state)

defineExpose({
	show
})
</script>

<style lang="scss" scoped>
.tui-datetime-picker {
	position: relative;
	z-index: 996;
}

.tui-picker-view {
	height: 100%;
	box-sizing: border-box;
}

.tui-mask {
	position: fixed;
	z-index: 997;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	background-color: rgba(0, 0, 0, 0.6);
	visibility: hidden;
	opacity: 0;
	transition: all 0.3s ease-in-out;
}

.tui-mask-show {
	visibility: visible !important;
	opacity: 1 !important;
}

.tui-header {
	z-index: 998;
	position: fixed;
	bottom: 0;
	left: 0;
	width: 100%;
	transition: all 0.3s ease-in-out;
	transform: translateY(100%);
}

.tui-date-header {
	width: 100%;
	height: 52rpx;
	display: flex;
	align-items: center;
	justify-content: space-between;
	font-size: 26rpx;
	line-height: 26rpx;
	/* #ifdef MP */
	box-shadow: 0 15rpx 10rpx -15rpx #efefef;
	/* #endif */
	/* #ifndef MP */
	box-shadow: 0 15rpx 10rpx -15rpx #888;
	/* #endif */
	position: relative;
	z-index: 2;
}

.tui-date-unit {
	flex: 1;
	text-align: center;
}

.tui-show {
	transform: translateY(0);
}

.tui-picker-header {
	width: 100%;
	height: 90rpx;
	padding: 0 40rpx;
	display: flex;
	justify-content: space-between;
	align-items: center;
	box-sizing: border-box;
	font-size: 32rpx;
	position: relative;
}

.tui-date-radius {
	border-top-left-radius: 20rpx;
	border-top-right-radius: 20rpx;
	overflow: hidden;
}

.tui-picker-header::after {
	content: '';
	position: absolute;
	border-bottom: 1rpx solid #eaeef1;
	-webkit-transform: scaleY(0.5);
	transform: scaleY(0.5);
	bottom: 0;
	right: 0;
	left: 0;
}

.tui-date__picker-body {
	width: 100%;
	/* height: 520rpx; */
	overflow: hidden;
}

.tui-date__column-item {
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 36rpx;
	color: #333;
}

.tui-font-size_32 {
	font-size: 32rpx !important;
}

.tui-date__unit-text {
	font-size: 24rpx !important;
	padding-left: 8rpx;
}

.tui-btn-picker {
	padding: 16rpx;
	box-sizing: border-box;
	text-align: center;
	text-decoration: none;
}

.tui-opacity {
	opacity: 0.5;
}
</style>
